package com.bjsxt;
/*死锁的概念：多个线程各自占有一些共享资源，并且互相等待其他线程占有的资源才
 * 能进行，而导致两个或者多个线程都在等待对方释放资源，都停止执行的情形。
 *   因此，某一个同步需要同时拥有“两个以上对象的锁”时，就可能会发生“死锁”
 * 的问题，比如，“化妆线程”需要同时拥有“镜子对象”、“口红对象”才能运行同步块。
 * 那么，实际运行时，“小红的化状”拥有“镜子对象”，“大红的化状线程”拥有了“口红对象”
 * 都在互相等待对方释放资源，才能化状。这样，两个线程就形成了互相等待，无法继续运行的“死锁状态”*/

/*死锁是由于“同步块需要同时持有多个对象锁造成”的，要解决这个问题，思路很简单
 * 就是：同一个代码块，不要同时有两个对象锁
 * 所以在多线程使用当中，不要用synchronized去嵌套另一个synchronized 作线程同步*/

/*口红类*/
class Lipstick{}
/*镜子*/
class Mirror{}
//化妆线程
class Makeup extends Thread{
    //标记
    private int flag;//flag=0:拿着口红，flag=1:拿镜子
    private String girlName;
    static Lipstick lipstick= new Lipstick();
    static Mirror mirror = new Mirror();

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    public String getGirlName() {
        return girlName;
    }

    public void setGirlName(String girlName) {
        this.girlName = girlName;
    }

    @Override
    public void run() {
        this.doMakeup();
    }
    //开始化妆
    //一个方法可以有多个线程
    public void doMakeup(){
        if(flag==0){
            //静态方法的对象，就是以这个类为对象锁
            synchronized (lipstick) {
                System.out.println(this.girlName + "拿着口红");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //拿镜子也要线程锁，因为她拿了镜，其他人不可以要
                //这个锁在另一个线程锁的内部  会造成死锁状态，不可取
                /*synchronized (mirror){
                    System.out.println(this.girlName+"拿着镜子");
                }*/
            }
            //解决方法，放在外面，不要嵌套
            synchronized (mirror){
                System.out.println(this.girlName+"拿着镜子");
            }
        }else {
            synchronized (mirror){
                System.out.println(this.girlName+"拿着镜子");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
               /* synchronized (lipstick){
                    System.out.println(this.girlName+"拿着口红");
                }*/
            }
            synchronized (lipstick){
                System.out.println(this.girlName+"拿着口红");
            }
        }
    }
}
public class DeadLockThread {
    public static void main(String[] args) {
        Makeup m = new Makeup();
        m.setFlag(0);
        m.setGirlName("大红");
        Makeup m1 = new Makeup();
        m1.setFlag(1);
        m1.setGirlName("小红");
        //启动线程   出现线程死锁  写代码不可以出现这情况
        m.start();
        m1.start();
    }
}
